package cn.iocoder.yudao.module.infra.service.base;

import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.common.exception.BusinessException;
import cn.iocoder.yudao.framework.common.util.cache.CacheUtils;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.module.infra.dal.dataobject.base.TreeDO;
import cn.iocoder.yudao.module.infra.dal.mysql.base.TreeMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;

/**
 * @author LifeFly
 */
@Service
public class TreeServiceImpl extends ServiceImpl<TreeMapper, TreeDO> implements TreeService {
    private static final Logger LOG = LogManager.getLogger(TreeServiceImpl.class);

    private static final String CACHE_TREE_MODEL = "m_t_a_";

    @Resource
    private TreeMapper treeMapper;

    @Override
    public List<TreeDO> listInId(List<Integer> ids) {
        return treeMapper.listAllByIdIn(ids);
    }

    @Override
    public List<String> listTreeType() {
        List<TreeDO> TreeDOs = treeMapper.listType();
        if (TreeDOs != null) {
            List<String> types = new ArrayList<>();
            for (TreeDO TreeDO : TreeDOs) {
                types.add(TreeDO.getType());
            }
            return types;
        }
        return null;
    }

    @Override
    public TreeDO getTreeByType(String type) {
        List<TreeDO> models = listTreeByType(type);
        if (CollectionUtil.isEmpty(models)) {
            return null;
        }
        for (int i = 0; i < models.size(); i++) {
            for (int j = (i + 1); j < models.size(); j++) {
                if (Objects.equals(models.get(j).getParentId(), models.get(i).getId())) {
                    models.get(i).getChildren().add(models.get(j));
                }
            }
        }
        return models.get(0);
    }

    @Override
    public List<TreeDO> listTreeByType(String type) {
        ValidationUtils.validNotBeNull(type, "type");
        List<TreeDO> models = CacheUtils.getList(CACHE_TREE_MODEL + type, TreeDO.class);
        if (!CollectionUtil.isEmpty(models)) {
            return models;
        }
        models = listByType(type);
        if (CollectionUtil.isEmpty(models)) {
            return null;
        }
        for (int i = 0; i < models.size(); i++) {
            for (int j = (i + 1); j < models.size(); j++) {
                if (Objects.equals(models.get(j).getParentId(), models.get(i).getId())) {
                    models.get(j).setFullName(models.get(i).getFullName() + "." + models.get(j).getName());
                    models.get(j).setFullLabel(models.get(i).getFullLabel() + "/" + models.get(j).getLabel());
                    models.get(j).setFullId(models.get(j).getFullParentId() + "_" + models.get(j).getId());
                }
            }
        }
        CacheUtils.set(CACHE_TREE_MODEL + type, models);
        return models;
    }

    private List<TreeDO> listByType(String type) {
        List<TreeDO> models = treeMapper.listByType(type);
        if (models == null || models.size() < 1) {
            return null;
        }
        //先按父ID排序
        models.sort(Comparator.comparingInt(TreeDO::getParentId));
        //同父ID按OrderNo排序
        models.sort((o1, o2) -> {
            if (!o1.getParentId().equals(o2.getParentId())) {
                return 0;
            } else {
                return o2.getOrderNo() - o1.getOrderNo();
            }
        });
        models.get(0).setFullName(models.get(0).getName());
        models.get(0).setFullLabel(models.get(0).getLabel());
        models.get(0).setFullId(models.get(0).getId() + "");
        return models;
    }

    @Override
    public void addTreeRoot(TreeDO root) throws BusinessException {
        if (root == null) {
            throw new BusinessException("请求参数为空");
        }
        if (StringUtils.isBlank(root.getType())) {
            throw new BusinessException("树类型不能为空");
        }
        if (StringUtils.isBlank(root.getLabel())) {
            throw new BusinessException("节点标签不能为空");
        }
        if (StringUtils.isBlank(root.getName())) {
            throw new BusinessException("节点名称不能为空");
        }
        TreeDO tree = getTreeByType(root.getType());
        if (tree != null) {
            throw new BusinessException("该类型已存在").addAttachment(root.getType());
        }
        root.setFullParentId("");
        root.setParentId(0);
        root.setName(root.getName().toUpperCase());
        root.setType(root.getType().toUpperCase());
        treeMapper.insert(root);
    }

    @Override
    public void addTreeNode(TreeDO node) throws BusinessException {
        if (node == null) {
            throw new BusinessException("请求参数异常");
        }
        if (node.getParentId() == null) {
            throw new BusinessException("节点父节点ID不能为空");
        }
        if (StringUtils.isBlank(node.getType())) {
            throw new BusinessException("节点类型不能为空");
        }
        if (StringUtils.isBlank(node.getLabel())) {
            throw new BusinessException("节点标签不能为空");
        }
        if (StringUtils.isBlank(node.getName())) {
            throw new BusinessException("节点名称不能为空");
        }
        TreeDO parentNode = treeMapper.selectById(node.getParentId());
        if (parentNode == null) {
            throw new BusinessException("父节点不存在");
        }
        if (StringUtils.isBlank(parentNode.getFullParentId())) {
            node.setFullParentId(parentNode.getId() + "");
        } else {
            node.setFullParentId(parentNode.getFullParentId() + "_" + parentNode.getId());
        }
        node.setName(node.getName().toUpperCase());
        node.setType(node.getType().toUpperCase());
        treeMapper.insert(node);
        CacheUtils.delete(CACHE_TREE_MODEL + node.getType());
    }

    @Override
    public void editTreeNode(Integer id, String label, String name, int orderNo, String remark, String updateId) throws BusinessException {
        ValidationUtils.validNotBeNull(id, "节点ID不能为空");
        ValidationUtils.validNotBeNull(label, "节点标签不能为空");
        ValidationUtils.validNotBeNull(updateId, "更新人员不能为空");
        ValidationUtils.validNotBeNull(name, "name");
        TreeDO upNode = treeMapper.selectById(id);
        TreeDO TreeDO = new TreeDO();
        TreeDO.setId(id);
        TreeDO.setLabel(label);
        TreeDO.setName(name.toUpperCase());
        TreeDO.setOrderNo(orderNo);
        TreeDO.setRemark(remark);
        TreeDO.setUpdater(updateId);
        treeMapper.updateById(TreeDO);
        CacheUtils.delete(CACHE_TREE_MODEL + upNode.getType());
    }

    @Override
    public void delTreeNode(Integer id, String updateId) throws BusinessException {
        if (id == null) {
            throw new BusinessException("删除节点ID不能为空");
        }
        TreeDO delNode = treeMapper.selectById(id);
        if (delNode == null) {
            throw new BusinessException("删除节点不存在");
        }
        String fullId = delNode.getFullParentId() + "_" + delNode.getId();
        LOG.info("操作人:{}执行删除节点:{}及其子节点:{}操作", updateId, delNode.getId(), fullId);
        treeMapper.deleteById(delNode.getId());
        treeMapper.delByFullParentIdLike(fullId + "%");
        CacheUtils.delete(CACHE_TREE_MODEL + delNode.getType());
    }
}




